"""
开发计划 API 路由

提供基于 MySQL 存储的开发计划增删改查能力
"""

from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel, Field
from typing import List, Optional, Literal
from sqlalchemy.orm import Session
from sqlalchemy import and_
from database import get_db, init_db
from model.models import Task, Stage, generate_id
import logging
from datetime import datetime, timezone

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/development-plan", tags=["development-plan"])


def _now_iso() -> str:
    """返回 UTC ISO 时间字符串"""
    return datetime.now(timezone.utc).isoformat()


StatusLiteral = Literal["progress", "done", "blocked"]


class StageInput(BaseModel):
    name: str = Field(..., min_length=1, max_length=50)
    completed: bool = Field(False, description="是否完成")


class StageUpdate(BaseModel):
    name: Optional[str] = Field(None, min_length=1, max_length=50)
    completed: Optional[bool] = Field(None, description="是否完成")


class TaskInput(BaseModel):
    name: str = Field(..., min_length=1, max_length=80)
    due: str = Field(..., description="截止日期，格式 YYYY-MM-DD")
    status: StatusLiteral = "progress"
    risk: Optional[str] = Field("", max_length=200)
    priority: Optional[int] = Field(None, ge=0, description="优先级，数字越小优先级越高")
    stages: Optional[List[dict]] = Field(default_factory=list, description="任务阶段列表")


class TaskUpdate(BaseModel):
    name: Optional[str] = Field(None, min_length=1, max_length=80)
    due: Optional[str] = Field(None, description="截止日期，格式 YYYY-MM-DD")
    status: Optional[StatusLiteral] = None
    risk: Optional[str] = Field(None, max_length=200)
    priority: Optional[int] = Field(None, ge=0, description="优先级，数字越小优先级越高")
    stages: Optional[List[dict]] = None


@router.get("")
async def get_plan(db: Session = Depends(get_db)):
    """获取开发计划"""
    try:
        # 获取所有未归档的任务（archived_at 为 None）
        tasks = db.query(Task).filter(Task.archived_at.is_(None)).all()
        
        # 优先按 priority 排序（priority 越小优先级越高，排在越前面；priority 为 None 的排在最后）
        tasks.sort(key=lambda x: (x.priority is None, x.priority if x.priority is not None else 999))
        
        # 转换为字典格式
        tasks_data = [task.to_dict() for task in tasks]
        
        return {
            "code": 200,
            "msg": "success",
            "data": {
                "tasks": tasks_data,
                "archived": []  # 归档任务通过单独的接口获取
            }
        }
    except Exception as e:
        logger.error(f"获取开发计划失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"获取开发计划失败: {str(e)}")


@router.get("/archived")
async def get_archived_tasks(db: Session = Depends(get_db)):
    """获取已归档的任务"""
    try:
        # 获取所有已归档的任务（archived_at 不为 None）
        archived_tasks = db.query(Task).filter(Task.archived_at.isnot(None)).all()
        
        # 按归档时间倒序排列（最新的在前）
        archived_tasks.sort(key=lambda x: x.archived_at or datetime.min.replace(tzinfo=timezone.utc), reverse=True)
        
        # 转换为字典格式
        archived_data = [task.to_dict() for task in archived_tasks]
        
        return {"code": 200, "msg": "success", "data": archived_data}
    except Exception as e:
        logger.error(f"获取归档任务失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"获取归档任务失败: {str(e)}")


@router.post("/tasks/{task_id}/stages")
async def create_task_stage(task_id: str, stage: StageInput, db: Session = Depends(get_db)):
    """为任务新增阶段"""
    try:
        # 查找任务
        task = db.query(Task).filter(Task.id == task_id, Task.archived_at.is_(None)).first()
        if not task:
            raise HTTPException(status_code=404, detail="任务不存在")
        
        # 创建阶段
        stage_entry = Stage(
            id=generate_id("stage"),
            task_id=task_id,
            name=stage.name,
            completed=stage.completed
        )
        
        db.add(stage_entry)
        task.updated_at = datetime.now(timezone.utc)
        db.commit()
        db.refresh(stage_entry)
        
        return {"code": 200, "msg": "stage created", "data": stage_entry.to_dict()}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"创建任务阶段失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"创建任务阶段失败: {str(e)}")


@router.put("/tasks/{task_id}/stages/{stage_id}")
async def update_task_stage(
    task_id: str, 
    stage_id: str, 
    payload: StageUpdate,
    db: Session = Depends(get_db)
):
    """更新任务阶段"""
    try:
        # 查找任务
        task = db.query(Task).filter(Task.id == task_id, Task.archived_at.is_(None)).first()
        if not task:
            raise HTTPException(status_code=404, detail="任务不存在")
        
        # 查找阶段
        stage = db.query(Stage).filter(
            Stage.id == stage_id,
            Stage.task_id == task_id
        ).first()
        if not stage:
            raise HTTPException(status_code=404, detail="阶段不存在")
        
        # 更新字段
        updates = payload.dict(exclude_unset=True)
        if not updates:
            raise HTTPException(status_code=400, detail="没有可更新的字段")
        
        for key, value in updates.items():
            setattr(stage, key, value)
        
        stage.updated_at = datetime.now(timezone.utc)
        task.updated_at = datetime.now(timezone.utc)
        db.commit()
        db.refresh(stage)
        
        return {"code": 200, "msg": "stage updated", "data": stage.to_dict()}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"更新任务阶段失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"更新任务阶段失败: {str(e)}")


@router.delete("/tasks/{task_id}/stages/{stage_id}")
async def delete_task_stage(task_id: str, stage_id: str, db: Session = Depends(get_db)):
    """删除任务阶段"""
    try:
        # 查找任务
        task = db.query(Task).filter(Task.id == task_id, Task.archived_at.is_(None)).first()
        if not task:
            raise HTTPException(status_code=404, detail="任务不存在")
        
        # 查找并删除阶段
        stage = db.query(Stage).filter(
            Stage.id == stage_id,
            Stage.task_id == task_id
        ).first()
        if not stage:
            raise HTTPException(status_code=404, detail="阶段不存在")
        
        db.delete(stage)
        task.updated_at = datetime.now(timezone.utc)
        db.commit()
        
        return {"code": 200, "msg": "stage deleted", "data": {"id": stage_id}}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"删除任务阶段失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"删除任务阶段失败: {str(e)}")


@router.post("/tasks")
async def create_task(task: TaskInput, db: Session = Depends(get_db)):
    """新增任务"""
    try:
        # 如果没有设置优先级，设置为当前最大优先级+1
        priority = task.priority
        if priority is None:
            max_priority_task = db.query(Task).filter(
                Task.archived_at.is_(None),
                Task.priority.isnot(None)
            ).order_by(Task.priority.desc()).first()
            
            if max_priority_task:
                priority = max_priority_task.priority + 1
            else:
                priority = 0
        
        # 创建任务
        task_entry = Task(
            id=generate_id("task"),
            name=task.name,
            due=task.due,
            status=task.status,
            risk=task.risk or "",
            priority=priority
        )
        
        # 如果有初始阶段，创建阶段
        if task.stages:
            for stage_data in task.stages:
                stage = Stage(
                    id=generate_id("stage"),
                    task_id=task_entry.id,
                    name=stage_data.get("name", ""),
                    completed=stage_data.get("completed", False)
                )
                task_entry.stages.append(stage)
        
        db.add(task_entry)
        db.commit()
        db.refresh(task_entry)
        
        return {"code": 200, "msg": "task created", "data": task_entry.to_dict()}
    except Exception as e:
        db.rollback()
        logger.error(f"创建任务失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"创建任务失败: {str(e)}")


@router.put("/tasks/{task_id}")
async def update_task(task_id: str, payload: TaskUpdate, db: Session = Depends(get_db)):
    """更新任务"""
    try:
        # 查找任务（未归档的）
        task = db.query(Task).filter(Task.id == task_id, Task.archived_at.is_(None)).first()
        if not task:
            raise HTTPException(status_code=404, detail="任务不存在")
        
        # 更新字段
        updates = payload.dict(exclude_unset=True)
        if not updates:
            raise HTTPException(status_code=400, detail="没有可更新的字段")
        
        # 如果传入了 stages，更新阶段（先删除旧的，再创建新的）
        if "stages" in updates:
            stages_data = updates.pop("stages")
            # 删除所有现有阶段
            db.query(Stage).filter(Stage.task_id == task_id).delete()
            # 创建新阶段
            for stage_data in stages_data:
                stage = Stage(
                    id=generate_id("stage"),
                    task_id=task_id,
                    name=stage_data.get("name", ""),
                    completed=stage_data.get("completed", False)
                )
                task.stages.append(stage)
        
        # 更新其他字段
        for key, value in updates.items():
            setattr(task, key, value)
        
        task.updated_at = datetime.now(timezone.utc)
        db.commit()
        db.refresh(task)
        
        return {"code": 200, "msg": "task updated", "data": task.to_dict()}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"更新任务失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"更新任务失败: {str(e)}")


@router.delete("/tasks/{task_id}")
async def delete_task(task_id: str, db: Session = Depends(get_db)):
    """删除任务"""
    try:
        # 查找任务（未归档的）
        task = db.query(Task).filter(Task.id == task_id, Task.archived_at.is_(None)).first()
        if not task:
            raise HTTPException(status_code=404, detail="任务不存在")
        
        # 删除任务（级联删除阶段）
        db.delete(task)
        db.commit()
        
        return {"code": 200, "msg": "task deleted", "data": {"id": task_id}}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"删除任务失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"删除任务失败: {str(e)}")


@router.post("/tasks/{task_id}/archive")
async def archive_task(task_id: str, db: Session = Depends(get_db)):
    """归档任务"""
    try:
        # 查找任务（未归档的）
        task = db.query(Task).filter(Task.id == task_id, Task.archived_at.is_(None)).first()
        if not task:
            raise HTTPException(status_code=404, detail="任务不存在")
        
        # 设置归档时间
        task.archived_at = datetime.now(timezone.utc)
        # 移除 priority 字段（归档任务不需要优先级）
        task.priority = None
        task.updated_at = datetime.now(timezone.utc)
        
        db.commit()
        db.refresh(task)
        
        return {"code": 200, "msg": "task archived", "data": task.to_dict()}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"归档任务失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"归档任务失败: {str(e)}")


@router.post("/tasks/{task_id}/unarchive")
async def unarchive_task(task_id: str, db: Session = Depends(get_db)):
    """取消归档任务"""
    try:
        task = db.query(Task).filter(Task.id == task_id).first()
        if not task:
            raise HTTPException(status_code=404, detail="任务不存在")

        if task.archived_at is None:
            raise HTTPException(status_code=400, detail="任务未归档")

        max_priority_task = db.query(Task).filter(
            Task.archived_at.is_(None),
            Task.priority.isnot(None)
        ).order_by(Task.priority.desc()).first()

        task.priority = (max_priority_task.priority + 1) if max_priority_task else 0
        task.archived_at = None
        task.updated_at = datetime.now(timezone.utc)

        db.commit()
        db.refresh(task)

        return {"code": 200, "msg": "task unarchived", "data": task.to_dict()}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"取消归档任务失败: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"取消归档任务失败: {str(e)}")
